package com.mock.android_location_mocker
import android.app.Activity
import android.content.Context.LOCATION_SERVICE
import android.location.LocationManager
import android.provider.Settings
import android.content.Intent;
import android.location.Location
import android.location.provider.ProviderProperties
import android.os.Build
import android.os.Bundle
import android.os.SystemClock
import android.util.Log
import androidx.annotation.RequiresApi
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
class AndroidLocationMockerPlugin: FlutterPlugin, MethodCallHandler ,ActivityAware{
  private lateinit var t: Thread
  private lateinit var activity: Activity
  private lateinit var locationManager: LocationManager
  private lateinit var channel : MethodChannel
  private var running:Boolean=true
  override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "android_location_mocker")
    channel.setMethodCallHandler(this)
  }

  @RequiresApi(Build.VERSION_CODES.S)
  override fun onMethodCall(call: MethodCall, result: Result) {
    when(call.method){
      "isReady"->{
        try {
          locationManager.addTestProvider(LocationManager.GPS_PROVIDER,
            false,
            false,
            false,
            false,
            false,
            false,
            false,
            ProviderProperties.POWER_USAGE_HIGH,
            ProviderProperties.ACCURACY_FINE)
          locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true)
          locationManager.removeTestProvider(LocationManager.GPS_PROVIDER)
          result.success(true)
        }catch (e:Exception){
          e.printStackTrace()
          result.success(false)
        }
      }
      "isOpenDevMode"->{
        val isOpenDevMode:Boolean=Settings.Secure.getInt(activity.getContentResolver(), "development_settings_enabled", 0) > 0
        result.success(isOpenDevMode)
      }
      "openDevMode"->{
        result.success(true)
        val intent=Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
        activity.startActivity(intent)
      }
      "startMock"->{
        result.success(true)
        val useGps:Boolean=call.argument<Map<String,Any>>("common")?.get("useGps")as Boolean
        val useNetwork:Boolean=call.argument<Map<String,Any>>("common")?.get("useNetwork")as Boolean
        val frequency_ms:Int=call.argument<Map<String,Any>>("common")?.get("frequency_ms")as Int
        val lng:Double=call.argument<Map<String,Any>>("mock_location")?.get("lng")as Double
        val lat:Double=call.argument<Map<String,Any>>("mock_location")?.get("lat")as Double
        Log.i("emmmmmmmmmm", "onMethodCall useGps: $useGps")
        Log.i("emmmmmmmmmm", "onMethodCall useNetwork: $useNetwork")
        Log.i("emmmmmmmmmm", "onMethodCall frequency_ms: $frequency_ms")
        Log.i("emmmmmmmmmm", "onMethodCall lng: $lng")
        Log.i("emmmmmmmmmm", "onMethodCall lat: $lat")
        startMock(useGps,useNetwork,frequency_ms.toLong(), lng,lat)
      }
      "stopMock"->{
        result.success(true)
        stopMock()
      }
    }
  }

  @RequiresApi(Build.VERSION_CODES.S)
  private fun startMock(useGps: Boolean, useNetwork: Boolean, frequencyMs: Long, lng: Double, lat: Double) {
    if(useGps){
      locationManager.addTestProvider(
        LocationManager.GPS_PROVIDER,
        false,
        false,
        false,
        false,
        false,
        false,
        false,
        ProviderProperties.POWER_USAGE_HIGH,
        ProviderProperties.ACCURACY_FINE
      )
      println("已设置gps")
      locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true)
    }
    if(useNetwork){
      locationManager.addTestProvider(
        LocationManager.NETWORK_PROVIDER,
        false,
        false,
        false,
        false,
        false,
        false,
        false,
        ProviderProperties.POWER_USAGE_HIGH,
        ProviderProperties.ACCURACY_FINE
      )
      println("已设置net")
      locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true)
    }
    startThread(useGps,useNetwork,frequencyMs,lat,lng)
  }

  private fun startThread(useGps: Boolean, useNetwork: Boolean,frequencyMs: Long, lat: Double, lng: Double) {
    running=true
    t=Thread{
      run{
        while (running) {
          if (useGps){
            setGpsLocation(lat,lng)
          }
          if(useNetwork){
            setNetworkLocation(lat,lng)
          }
          Thread.sleep(frequencyMs)
        }
      }
    }
    t.start()
  }
  private fun genLocation(provider:String): Location {
    val location = Location(provider)
    location.altitude = 10.0
    location.accuracy = 0f
    val bundle= Bundle()
    bundle.putInt("satellites",7)
    location.extras=bundle
    location.time=System.currentTimeMillis()
    location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
    location.bearing= 0F
    location.speed= 0F
    return location
  }
  private fun setNetworkLocation(lat: Double, lng: Double) {
    val location=genLocation(LocationManager.NETWORK_PROVIDER)
    location.latitude=lat
    location.longitude= lng
    locationManager.setTestProviderLocation(LocationManager.NETWORK_PROVIDER,location)
  }

  private fun setGpsLocation(lat: Double, lng: Double) {
    val location=genLocation(LocationManager.GPS_PROVIDER)
    location.latitude=lat
    location.longitude=lng
    locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER,location)
  }
  @RequiresApi(Build.VERSION_CODES.S)
  private fun stopMock() {
    running=false
    if(locationManager.hasProvider(LocationManager.GPS_PROVIDER)){
      locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true)
      locationManager.removeTestProvider(LocationManager.GPS_PROVIDER)
    }
    if(locationManager.hasProvider(LocationManager.NETWORK_PROVIDER)){
      locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true)
      locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER)
    }
//    t.interrupt()
  }
  override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }

  override fun onAttachedToActivity(binding: ActivityPluginBinding) {
    activity=binding.activity
    locationManager = binding.activity.getSystemService(LOCATION_SERVICE) as LocationManager
  }

  override fun onDetachedFromActivityForConfigChanges() {
  }

  override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
  }

  override fun onDetachedFromActivity() {
  }
}
